package com.smitish.vueblog.controller;


import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smitish.vueblog.common.lang.Result;
import com.smitish.vueblog.entity.Blog;
import com.smitish.vueblog.entity.Collection;
import com.smitish.vueblog.entity.Comment;
import com.smitish.vueblog.entity.Logs;
import com.smitish.vueblog.service.*;
import com.smitish.vueblog.util.OssUtil;
import com.smitish.vueblog.util.ShiroUtil;
import com.smitish.vueblog.vo.BlogUserVO;
import org.apache.catalina.security.SecurityUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Smitish
 * @since 2020-11-30
 */
@RestController
public class BlogController {

    @Autowired
    BlogService blogService;

    @Autowired
    UserService userService;

    @Autowired
    LogsService logsService;

    @Autowired
    CollectionService collectionService;

    @Autowired
    CommentService commentService;

    @Autowired
    OssUtil ossUtil;

    /**
     * 博客表和用户表 多表连接
     *
     * @param currentPage 当前页码
     * @return 返回带作者名字的博客结果集
     */
    @GetMapping("/blogs")
    public Result lists(@RequestParam(defaultValue = "1") Integer currentPage) {
        Page<BlogUserVO> blogUser = blogService.getBlogUser(new Page<>(currentPage, 16));
        return Result.success(blogUser);
    }

    /**
     * 需要验证身份查询个人发表博客的api
     *
     * @param currentPage 当前页码
     * @return 每一个的数据集
     */
    @RequiresAuthentication
    @GetMapping("/getMyBlog")
    public Result getMyBlog(@RequestParam(defaultValue = "1") Integer currentPage) {
        Long id = ShiroUtil.getProfile().getId();
        Page page = new Page(currentPage, 5);
        IPage pageData = blogService.page(page, new QueryWrapper<Blog>()
                .orderByDesc("created")
                .eq("user_id", id));
        return Result.success(pageData);
    }

    /**
     * 通过某一个用户ID查询其发表的博客
     *
     * @param id          用户id
     * @param currentPage 当前页码
     * @return 返回博客结果集
     */
    @GetMapping("/getBlog/{id}")
    public Result getBlog(@PathVariable(name = "id") Long id, @RequestParam(defaultValue = "1") Integer currentPage) {
        // 设置每一页 博客的数量
        Page page = new Page(currentPage, 5);
        // 分页查询
        IPage iPage = blogService.page(page, new QueryWrapper<Blog>().orderByDesc("created").eq("user_id", id));
        // 返回结果集
        return Result.success(iPage);
    }

    /**
     * 根据博客ID 返回对应的博客内容
     *
     * @param id 博客ID
     * @return blog
     */
    @GetMapping("/blog/{id}")
    public Result detail(@PathVariable(name = "id") Long id) {
        Blog blog = blogService.getById(id);
        Assert.notNull(blog, "该博客已被删除");
        return Result.success(blog);
    }


    /**
     * 编辑或者发布新博客
     *
     * @param blog 需要编辑的博客内容实体
     * @return 返回编辑结果
     */
    @RequiresAuthentication
    @PostMapping("/blog/edit")
    public Result edit(@Validated @RequestBody Blog blog) {
        boolean isEdit = false;
        Blog temp = null;
        if (blog.getId() != null) {
            // 编辑
            isEdit = true;
            temp = blogService.getById(blog.getId());
            // 只能编辑自己的文章
            // >> TODO 需要注意后面的longValue()
            Assert.isTrue(ShiroUtil.getProfile().getId().longValue() == temp.getUserId().longValue(), "没有权限编辑");
        } else {
            temp = new Blog();
            temp.setUserId(ShiroUtil.getProfile().getId());
            temp.setCreated(LocalDateTime.now());
            temp.setStatus(0);
        }
        // 设置默认图片
        if (blog.getImage().isEmpty()) {
            blog.setImage("https://cosy.demo.nicetheme.xyz/wp-content/uploads/2020/08/2020082618051678.jpg");
        }
        BeanUtils.copyProperties(blog, temp, "id", "userId", "created", "status");
        Logs logs = new Logs();
        logs.setUserId(ShiroUtil.getProfile().getId());
        if (isEdit) {
            if (blogService.saveOrUpdate(temp)) {
                logs.setLogContent("重新编辑了\"" + blog.getTitle() + "\"");
                logsService.saveOrUpdate(logs);
                return Result.succ(200, "编辑成功", null);
            }
            return Result.fail("编辑失败");
        } else {
            if (blogService.saveOrUpdate(temp)) {
                logs.setLogContent("发布了\"" + blog.getTitle() + "\"");
                logsService.saveOrUpdate(logs);
                return Result.succ(200, "发布成功", null);
            }
            return Result.fail("发布失败");
        }
    }


    /**
     * 通过 身份验证 删除博客
     *
     * @param id 博客id
     * @return 返回删除结果
     */
    @RequiresAuthentication
    @DeleteMapping("/blog/delete/{id}")
    public Result deleteBlog(@PathVariable(name = "id") Long id) {
        // 用户ID
        Long uid = ShiroUtil.getProfile().getId();
        // 判断删除博客的作者是否是本人
        if (uid.equals(blogService.getById(id).getUserId())) {
            boolean b = blogService.removeById(id);
            // 删除博客之后 需要更新收藏表
            if (b) {
                collectionService.remove(new QueryWrapper<Collection>().eq("post_id", id));
                commentService.remove(new QueryWrapper<Comment>().eq("post_id", id));
                return Result.succ(200, "删除成功", null);
            }
            return Result.fail("删除失败");
        } else {
            return Result.fail("没有权限删除此博客");
        }
    }

    /**
     * @return 返回一篇的随机文章
     */
    @GetMapping("/blog/random")
    public Result getRandomBlog() {
        List<Blog> list = blogService.list();
        int size = list.size();
        //获得当前时间的毫秒数 做为随机数的种子传进去
        long l = System.currentTimeMillis();
        Random random = new Random(l);
        return Result.success(list.get(random.nextInt(size)));
    }


    @RequiresAuthentication
    @PostMapping("/blog/uploadImage")
    public Result uploadImage(@RequestParam("file") MultipartFile file) {
        // 返回上传之后的url
        try {
            String url = ossUtil.uploadFile(file); //调用OSS工具类
            return Result.succ(200, "上传成功", url);
        } catch (Exception e) {
            return Result.fail("上传失败");
        }

    }


    @GetMapping("/blog/search")
    public Result getUnknownBlog(@RequestParam(defaultValue = "null") String context, @RequestParam(defaultValue = "1") Integer currentPage) {
        StringBuilder sb = new StringBuilder();
        sb.append("%");
        sb.append(context);
        sb.append("%");
        Page<BlogUserVO> unknownBlog = blogService.getUnknownBlog(sb.toString(), new Page<>(currentPage, 16));
        return Result.succ(200, "获取成功", unknownBlog);
    }
}
